#include <iostream>
#include <functional>
#include <memory>
#include "muduo/net/EventLoopThread.h"
#include "muduo/net/TcpClient.h"
#include "muduo/net/TcpConnection.h"
#include "muduo/base/CountDownLatch.h"

class Client
{
private:
    /*连接建立成功和连接断开回调*/
    void onConnection(const muduo::net::TcpConnectionPtr& conn)
    {
        if(conn->connected()==true)
        {
            _latch.countDown();//唤醒在条件变量上阻塞的线程
            _conn=conn;
            std::cout<<"连接建立成功\n";
        }
        else
        {
            _conn.reset();//连接断开时的操作
            std::cout<<"连接断开\n";
        }
    }

    void onMessage(const muduo::net::TcpConnectionPtr& conn,muduo::net::Buffer* buffer,muduo::Timestamp)
    {
        std::cout<<"翻译结果: "<<buffer->retrieveAllAsString()<<std::endl;
    }

public:
    Client(const std::string& ip="127.0.0.1",uint16_t port=8080)
        :_latch(1)
        ,_client(_loop_thread.startLoop(),muduo::net::InetAddress(ip,port),"client")
    {
        _client.setConnectionCallback(std::bind(&Client::onConnection,this,std::placeholders::_1));
        _client.setMessageCallback(std::bind(&Client::onMessage,this,std::placeholders::_1,std::placeholders::_2,std::placeholders::_3));
    }

    void connect()
    {
        _client.connect();//这个链接请求不是立即的,为了防止链接还没有建立就执行后续逻辑，需要等待
        _latch.wait();//阻塞等待，知道连接建立成功
    }

    bool send(const std::string& message)
    {
        if(_conn->connected()==true)
        {
            _conn->send(message);
            return true;
        }
        return false;
    }

    ~Client()=default;

private:
    muduo::CountDownLatch _latch;//互斥+条件变量
    muduo::net::EventLoopThread _loop_thread;//线程绑定的EventLoop  他的存在是为了让client是在线程中执行的,不会影响主线程逻辑
    muduo::net::TcpClient _client;//搭建客户端
    muduo::net::TcpConnectionPtr _conn;
};

int main()
{
    std::unique_ptr<Client> ptr(new Client());
    ptr->connect();
    while(true)
    {
        std::string str;
        std::getline(std::cin,str);
        ptr->send(str);
    }
    return 0;
}